package com.newtouch.bxzs.business.train.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.newtouch.bxzs.business.train.mapper.ExaminationMapper;
import com.newtouch.bxzs.business.train.mapper.ExaminationQuestionsOptionMapper;
import com.newtouch.bxzs.business.train.mapper.ExaminationUserMapMapper;
import com.newtouch.bxzs.business.train.mapper.UserExaminationMapper;
import com.newtouch.bxzs.business.train.model.bo.*;
import com.newtouch.bxzs.business.train.model.vo.UserExaminationQuestionsVO;
import com.newtouch.bxzs.business.train.model.vo.UserExaminationResultVO;
import com.newtouch.bxzs.business.train.model.vo.UserExaminationVO;
import com.newtouch.bxzs.business.train.model.vo.UserWrongCollectionQuestionsVO;
import com.newtouch.bxzs.business.train.service.UserExaminationService;
import com.newtouch.bxzs.common.base.BaseErrorEnum;
import com.newtouch.bxzs.common.base.BaseException;
import com.newtouch.bxzs.common.base.em.SystemParamsEnum;
import com.newtouch.bxzs.common.base.model.Examination;
import com.newtouch.bxzs.common.base.model.ExaminationQuestionsOption;
import com.newtouch.bxzs.common.base.model.ExaminationUserMap;
import com.newtouch.bxzs.common.base.model.UserExaminationResult;
import com.newtouch.bxzs.common.base.util.RedisUtils;
import com.newtouch.bxzs.common.base.util.UserDetailUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 用户考试管理ServiceImpl类
 *
 * <p>
 * <b>History:</b>
 * <table border="1">
 * <tr>
 * <th>Date</th>
 * <th>Operator</th>
 * <th>Memo</th>
 * </tr>
 * <tr>
 * <td>2021/3/25 9:46</td>
 * <td>dingqianbin</td>
 * <td>Create</td>
 * </tr>
 * </table>
 *
 * @author dingqianbin
 * @version 1.0.0
 * @since 1.0.0
 */
@Service
public class UserExaminationServiceImpl implements UserExaminationService {

    private static final Log logger = LogFactory.getLog(UserExaminationServiceImpl.class);

    @Autowired
    UserExaminationMapper userExaminationMapper;

    @Autowired
    RedisUtils redisUtils;

    @Autowired
    ExaminationQuestionsOptionMapper examinationQuestionsOptionMapper;

    @Autowired
    ExaminationUserMapMapper examinationUserMapMapper;

    @Autowired
    ExaminationMapper examinationMapper;

    @Override
    public UserExaminationInfoBO getUserExaminationInfo() {
        String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
        checkUserExaminationInfo(userId);
        UserExaminationInfoBO userExaminationInfoBO = userExaminationMapper.getUserExaminationInfo(userId);
        Integer recentExaminationRecordsNumber = Integer.valueOf(redisUtils.get(SystemParamsEnum.RECENT_EXAMINATION_RECORDS_NUMBER.getCode()));
        List<UserExaminationHistoryBO> userExaminationHistoryBOList = userExaminationMapper.getUserExaminationHistory(userId, recentExaminationRecordsNumber);
        userExaminationInfoBO.setUserExaminationHistoryBOList(userExaminationHistoryBOList);
        return userExaminationInfoBO;
    }

    /**
     * 处理处于考试中的考试
     *
     * @param userId 用户ID
     */
    private void checkUserExaminationInfo(String userId) {
        //1.查出考试中的考试
        List<ExaminationUserMap> examinationUserMapList = examinationUserMapMapper.selectList(new QueryWrapper<ExaminationUserMap>().eq("IS_PARTICIPATION_EXAMINATION", 1).eq("USER_ID",userId));
        //2.将考试中的考试先对比考试结束时间，在对比考试时间
        Date date = new Date();
        if(!CollectionUtils.isEmpty(examinationUserMapList)){
            for(ExaminationUserMap examinationUserMap : examinationUserMapList){
                Examination examination = examinationMapper.selectById(examinationUserMap.getExaminationId());
                if(date.compareTo(examination.getExaminationEndTime()) >= 0){
                    endExamination(examinationUserMap);
                }else {
                    long examinationDuration = examination.getExaminationDuration().intValue()*60L;
                    long usedExaminationDuration = (date.getTime() - examinationUserMap.getExaminationTime().getTime())/1000;
                    if(usedExaminationDuration >= examinationDuration){
                        endExamination(examinationUserMap);
                    }
                }
            }
        }
    }

    /**
     * 超过时间的考试直接计算分数并结束
     *
     * @param examinationUserMap 参考人员和考试对应关系实体类
     */
    private void endExamination(ExaminationUserMap examinationUserMap) {
        String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
        int rightCount = userExaminationMapper.selectCount(new QueryWrapper<UserExaminationResult>().eq("IS_CORRECT", 1).eq("EXAMINATION_ID",examinationUserMap.getExaminationId()).eq("USER_ID",userId));
        long examinationScore = (long) rightCount * Long.parseLong(redisUtils.get(SystemParamsEnum.SCORE_OF_EACH_QUESTION.getCode()));
        Date date = new Date();
        examinationUserMap.setIsParticipationExamination(2);
        examinationUserMap.setExaminationScore(Integer.parseInt(String.valueOf(examinationScore)));
        examinationUserMap.setExaminationTime(date);
        examinationUserMap.setUpdateUserId(userId);
        examinationUserMap.setUpdateTime(date);
        examinationUserMapMapper.updateById(examinationUserMap);
    }

    @Override
    public IPage<UserExaminationBO> getUserExaminationList(UserExaminationVO userExaminationVO) {
        if (StringUtils.isEmpty(userExaminationVO) || StringUtils.isEmpty(userExaminationVO.getExaminationType())) {
            logger.error("查询用户考试列表请求参数为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        Page<UserExaminationBO> page = new Page<>(userExaminationVO.getCurrentPage(), userExaminationVO.getPageSize());
        String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
        return userExaminationMapper.getUserExaminationList(page, userId, userExaminationVO.getExaminationType());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public UserJoinExaminationInfoBO getUserExaminationQuestions(UserExaminationQuestionsVO userExaminationQuestionsVO) {
        if (StringUtils.isEmpty(userExaminationQuestionsVO) || StringUtils.isEmpty(userExaminationQuestionsVO.getExaminationUserMapId()) || StringUtils.isEmpty(userExaminationQuestionsVO.getExaminationId()) || StringUtils.isEmpty(userExaminationQuestionsVO.getExaminationPaperId())) {
            logger.error("参加考试请求参数为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        //1.先将该试卷的试题全部插入用户考试结果表里面
        String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
        //未考的状态
        ExaminationUserMap examinationUser = examinationUserMapMapper.selectById(userExaminationQuestionsVO.getExaminationUserMapId());
        Date date = new Date();
        long examinationRemainingTime = 0;
        if(StringUtils.isEmpty(examinationUser.getIsParticipationExamination()) || 0 == examinationUser.getIsParticipationExamination()){
            List<ExaminationQuestionBO> examinationQuestionBOList = userExaminationMapper.selectExaminationQuestionBOList(userExaminationQuestionsVO.getExaminationPaperId());
            userExaminationMapper.batchInsert(userExaminationQuestionsVO, userId, examinationQuestionBOList);
            //2.将考试状态改为考试中，并插入参考时间
            ExaminationUserMap examinationUserMap = new ExaminationUserMap();
            examinationUserMap.setExaminationUserMapId(userExaminationQuestionsVO.getExaminationUserMapId());
            examinationUserMap.setIsParticipationExamination(1);
            examinationUserMap.setExaminationTime(date);
            examinationUserMap.setUpdateUserId(userId);
            examinationUserMap.setUpdateTime(date);
            examinationUserMapMapper.updateById(examinationUserMap);
            examinationRemainingTime = userExaminationQuestionsVO.getExaminationDuration().intValue() * 60L;
        }else if (1 == examinationUser.getIsParticipationExamination()){
            examinationRemainingTime = userExaminationQuestionsVO.getExaminationDuration().intValue() * 60L - (date.getTime()-examinationUser.getExaminationTime().getTime())/1000;
        }
        //3.将该试卷所有试题返回给前端
        UserJoinExaminationInfoBO userJoinExaminationInfoBO = new UserJoinExaminationInfoBO();
        userJoinExaminationInfoBO.setUserExaminationQuestionsBOList(userExaminationMapper.getUserExaminationQuestions(userExaminationQuestionsVO, userId));
        userJoinExaminationInfoBO.setExaminationRemainingTime(examinationRemainingTime);
        return userJoinExaminationInfoBO;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer updateUserExaminationResult(UserExaminationResultVO userExaminationResultVO) {
        if (StringUtils.isEmpty(userExaminationResultVO) || StringUtils.isEmpty(userExaminationResultVO.getUserExaminationResultId()) || StringUtils.isEmpty(userExaminationResultVO.getExaminationQuestionsId())) {
            logger.error("答题信息提交请求参数为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
        UserExaminationResult userExaminationResult = new UserExaminationResult();
        userExaminationResult.setUserExaminationResultId(userExaminationResultVO.getUserExaminationResultId());
        userExaminationResult.setIsCollect(userExaminationResultVO.getIsCollect());
        userExaminationResult.setUpdateUserId(userId);
        userExaminationResult.setUpdateTime(new Date());
        StringBuilder questionsOptions = new StringBuilder();
        String userExaminationQuestionsOption = userExaminationResultVO.getUserExaminationQuestionsOption();
        if (!StringUtils.isEmpty(userExaminationQuestionsOption)) {
            userExaminationResult.setUserExaminationQuestionsOption(userExaminationQuestionsOption);
            List<ExaminationQuestionsOption> examinationQuestionsOptions = examinationQuestionsOptionMapper.selectList(new QueryWrapper<ExaminationQuestionsOption>().eq("EXAMINATION_QUESTIONS_ID", userExaminationResultVO.getExaminationQuestionsId()).eq("IS_CORRECT",1).orderByAsc("EXAMINATION_QUESTIONS_OPTION"));
            for (ExaminationQuestionsOption examinationQuestionsOption: examinationQuestionsOptions){
                questionsOptions.append(",");
                questionsOptions.append(examinationQuestionsOption.getExaminationQuestionsOption());
            }
            if (userExaminationQuestionsOption.equals(questionsOptions.substring(1))) {
                userExaminationResult.setIsCorrect(1);
            }else{
                userExaminationResult.setIsCorrect(0);
            }
        }
        return userExaminationMapper.updateById(userExaminationResult);
    }

    @Override
    public IPage<UserWrongCollectionQuestionsBO> getWrongCollectionQuestions(UserWrongCollectionQuestionsVO userWrongCollectionQuestionsVO) {
        if(StringUtils.isEmpty(userWrongCollectionQuestionsVO) || StringUtils.isEmpty(userWrongCollectionQuestionsVO.getQuestionType())){
            logger.error("查询错题/收藏题列表请求参数为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        Page<UserWrongCollectionQuestionsBO> page = new Page<>(userWrongCollectionQuestionsVO.getCurrentPage(), userWrongCollectionQuestionsVO.getPageSize());
        return userExaminationMapper.getWrongCollectionQuestions(page,userWrongCollectionQuestionsVO.getQuestionType(), Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId());
    }

    @Override
    public UserQuestionBO getQuestionInfo(String examinationQuestionsId) {
        if(StringUtils.isEmpty(examinationQuestionsId)){
            logger.error("查询试题详情信息请求参数为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
        return userExaminationMapper.getQuestionInfo(examinationQuestionsId, userId);
    }

    @Override
    public String endOfAnswer(UserExaminationResultVO userExaminationResultVO) {
        if (StringUtils.isEmpty(userExaminationResultVO) || StringUtils.isEmpty(userExaminationResultVO.getExaminationUserMapId()) || StringUtils.isEmpty(userExaminationResultVO.getFlag()) || StringUtils.isEmpty(userExaminationResultVO.getExaminationId())) {
            logger.error("答题结束提交请求参数为空");
            throw new BaseException(BaseErrorEnum.REQUEST_DATA_NULL);
        }
        StringBuilder unansweredQuestionNumber = new StringBuilder();
        String userId = Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId();
        List<UserExaminationResult> userExaminationResults = userExaminationMapper.selectList(new QueryWrapper<UserExaminationResult>().eq("EXAMINATION_ID",userExaminationResultVO.getExaminationId()).eq("USER_ID",userId).isNull("USER_EXAMINATION_QUESTIONS_OPTION").orderByAsc("USER_EXAMINATION_QUESTIONS_TITLE_NUMBER"));
        if(!CollectionUtils.isEmpty(userExaminationResults)){
            for(UserExaminationResult userExaminationResult : userExaminationResults){
                unansweredQuestionNumber.append(",");
                unansweredQuestionNumber.append(userExaminationResult.getUserExaminationQuestionsTitleNumber());
            }
        }
        if(StringUtils.isEmpty(unansweredQuestionNumber.toString()) || "2".equals(userExaminationResultVO.getFlag())){
            String examinationUserMapId = userExaminationResultVO.getExaminationUserMapId();
            int rightCount = userExaminationMapper.selectCount(new QueryWrapper<UserExaminationResult>().eq("IS_CORRECT", 1).eq("EXAMINATION_ID",userExaminationResultVO.getExaminationId()).eq("USER_ID",userId));
            long examinationScore = (long) rightCount * Long.parseLong(redisUtils.get(SystemParamsEnum.SCORE_OF_EACH_QUESTION.getCode()));
            Date date = new Date();
            ExaminationUserMap examinationUserMap = new ExaminationUserMap();
            examinationUserMap.setExaminationUserMapId(examinationUserMapId);
            examinationUserMap.setIsParticipationExamination(2);
            examinationUserMap.setExaminationScore(Integer.parseInt(String.valueOf(examinationScore)));
            examinationUserMap.setExaminationTime(date);
            examinationUserMap.setUpdateUserId(Objects.requireNonNull(UserDetailUtil.getUserDetail()).getUserId());
            examinationUserMap.setUpdateTime(date);
            examinationUserMapMapper.updateById(examinationUserMap);
        }
        if(!StringUtils.isEmpty(unansweredQuestionNumber.toString())){
            return unansweredQuestionNumber.substring(1);
        }
        return null;
    }
}
